﻿#include "unrealircd.h"




CMD_FUNC(cmd_register);
CMD_FUNC(cmd_phoneRegister);
CMD_FUNC(cmd_EmailRegister);
bool check_nick(char *nick);
bool check_email(char *email);
bool check_sex(char *sex);
bool check_tel(char *tel);
bool user_name_check(char *str);
bool isNull(char *str);
void _registerSuccessCallfunc(HttpRequestData *requestData, long httpCode, Client *client,RegisterData *registerdata);
void _registerFaileCallfunc(HttpRequestData *requestData, Client *client,RegisterData *userData);
void create_user(Client *client,RegisterData *registerdata,char * email);

ModuleHeader MOD_HEADER
= {
	"usermodes/register",
	"1.1",
	"This module will add, delete, change, check and other operations to the database",
	"waitch",
	"unrealircd-5",
};

MOD_TEST(){
	MARK_AS_OFFICIAL_MODULE(modinfo);
	EfunctionAddVoid(modinfo->handle, EFUNC_REGISTER_USER_SUCCESS, _registerSuccessCallfunc);
	EfunctionAddVoid(modinfo->handle, EFUNC_REGISTER_USER_FAILE, _registerFaileCallfunc);
	return MOD_SUCCESS;
}

MOD_INIT()
{
	CommandAdd(modinfo->handle, "REGISTER", cmd_register, 8, CMD_UNLOGIN);
	CommandAdd(modinfo->handle, "PREGISTER", cmd_phoneRegister, 7, CMD_UNLOGIN);
	CommandAdd(modinfo->handle, "EREGISTER", cmd_EmailRegister, 6, CMD_UNLOGIN);
	
	return MOD_SUCCESS;
}

MOD_LOAD()
{
	return MOD_SUCCESS;
}

MOD_UNLOAD()
{
	return MOD_SUCCESS;
}
CMD_FUNC(cmd_register) {
	if (!IsAPPIdent(client)) {
		sendnumeric(client, ERR_WHITHOUTAPPIDENT);
		return;
	}
	if (parc != 9 || BadPtr(parv[8])) {
		sendnumeric(client, ERR_NEEDMOREPARAMS, "REGISTER");
		return;
	}
	//增加验证注册信息的
	if ((!isNull(parv[3]))&&check_tel(parv[3])) {
		int userTelExitNum=0;
		D_User  * d_user_tel=queryImUserByTel(parv[3],&userTelExitNum);
		db_D_UserFree(d_user_tel,userTelExitNum);
		if(userTelExitNum!=0){
			sendnumeric(client, RIGISTERUSERTELISUSED);
			return;
		}

	}

	if ((!isNull(parv[5])) && check_email(parv[5])) {
		int userEmailExitNum=0;
		D_User  * d_user_email=queryImUserByTel(parv[5],&userEmailExitNum);
		db_D_UserFree(d_user_email,userEmailExitNum);
		if(userEmailExitNum!=0){
			sendnumeric(client, RIGISTERUSERTELISUSED);
			return;
		}
	}
	//
	D_User *user=db_createUser();
	if (isNull(parv[1])) {
		sendnumeric(client, REGISTERNEEDMOREPARAM, "user_name");
		return;
	}
	else {
		if (!user_name_check(parv[1])) {
			sendnumeric(client, RIGISTERPARAMNOTRIGHT, "username");
			return;
		}
		int UserNameExitNum = 0;
		D_User *tempUser=queryImUserByUserName(parv[1], &UserNameExitNum);
		db_D_UserFree(tempUser,UserNameExitNum);
		if (UserNameExitNum != 0) {
			sendnumeric(client, RIGISTERUSERNAMEISUSED);
			return;
		}
		safe_strdup(user->user_name,parv[1]);
	}

	if (isNull(parv[2])) {
		sendnumeric(client, REGISTERNEEDMOREPARAM, "password");
		return;
	}
	else {
		safe_strdup(user->user_password,parv[2]);
	}
	if ((!isNull(parv[3]))&&check_tel(parv[3])) {
		safe_strdup(user->tel,parv[3]);
	}
	if ((!isNull(parv[4])) && check_sex(parv[4])) {
		user->sex = malloc(sizeof(int));
		*(user->sex) = atoi(parv[4]);
	}
	char * email = NULL;
	if ((!isNull(parv[5])) && check_email(parv[5])) {
		safe_strdup(email,parv[5]);
	}
	if ((!isNull(parv[6])) && check_nick(parv[6])) {
		safe_strdup(user->user_nick,parv[6]);
	}
	D_TimeStamp *timestamp=safe_alloc(sizeof(D_TimeStamp));
	D_getCurrectTime(timestamp);
	user->created_at = timestamp;
	ircd_log(LOG_ERROR,"client:%p",client);
	RegisterData *registerdata=safe_alloc(sizeof(RegisterData));
	registerdata->d_user=user;
	registerdata->openid=NULL;
	if(!isNull(parv[7])&&!isNull(parv[8])&&is_digist_string(parv[8],strlen(parv[8]))){
		safe_strdup(registerdata->openid,parv[7]);
		registerdata->thirdid=atoi(parv[8]);
		int len=0;
		D_third_login * third = queryImThirdLoginByOpenidAndThirdid(parv[7],registerdata->thirdid,&len);
		db_D_ThirdLoginFree(third,len);
		if(len!=0){
			sendnumeric(client, RIGISTERSQLERROR, "third is already in used");
			return;
		}
	}

	//creat_gitlib_user(user->user_name,user->user_nick,user->user_password,user->email,client,registerdata);
	create_user(client,registerdata,email);
}

/**
 * 手机注册账号
 * parv[1] 手机号
 * parv[2] 手机验证码
 * parv[3] 昵称
 * parv[4] 密码
 * parv[5] 区域编号
 * parv[6] 第三方的openid
 * parv[7] 第三方的编号 0是QQ，1是微信
 */
CMD_FUNC(cmd_phoneRegister){
	if (!IsAPPIdent(client)) {
		sendnumeric(client, ERR_WHITHOUTAPPIDENT);
		return;
	}
	if (parc != 8 || BadPtr(parv[7])) {
		sendnumeric(client, ERR_NEEDMOREPARAMS, "PREGISTER");
		return;
	}

	//增加验证注册信息的

	//
	
	if (isNull(parv[1])) {
		sendnumeric(client, REGISTERNEEDMOREPARAM, "tel");
		return;
	}
	else {
		if (!check_tel(parv[1])) {
			sendnumeric(client, RIGISTERPARAMNOTRIGHT, "tel");
			return;
		}
		int UsertelExitNum = 0;
		D_User *tempUser=queryImUserByTel(parv[1], &UsertelExitNum);
		db_D_UserFree(tempUser,UsertelExitNum);
		if (UsertelExitNum != 0) {
			sendnumeric(client, RIGISTERUSERNAMEISUSED);
			return;
		}
		
	}
	//验证手机验证码是否正确
	int sms_data_len=0;
	D_im_sms *sms_data=queryImSMSByValueAndType(parv[1],SMS_STATUS_REGISTER,SMS_MODE_PHONE,5,&sms_data_len);
	if(sms_data_len!=1){
		sendnumeric(client, SMSVALIDATIONFAILED);
		return;
	}
	if(strcmp(parv[2],sms_data->code)){
		sendnumeric(client, SMSVALIDATIONFAILED);
		return;
	}
	
	*(sms_data->used)=1;
	int sms_updata=0;
	char s_sms_updata[255]="";
	D_im_sms *sms_data_update=updataImSMS(sms_data,&sms_updata,s_sms_updata);
	db_D_ImSMSFree(sms_data_update,sms_updata);
	db_D_ImSMSFree(sms_data,sms_data_len);
	if(isNull(parv[3])){
		sendnumeric(client, REGISTERNEEDMOREPARAM, "user_nick");
		return;
	}
	if (isNull(parv[4])) {
		sendnumeric(client, REGISTERNEEDMOREPARAM, "password");
		return;
	}
	if (isNull(parv[5])) {
		sendnumeric(client, REGISTERNEEDMOREPARAM, "area_code");
		return;
	}



	D_User *user=db_createUser();
	char auto_user_name[31];
	char *temp=NULL;
	safe_strdup(temp,parv[1]);
	if(strlen(temp)>15){
		temp[15]='\0';
	}

	char *randomCode=random_digist(5);
	sprintf(auto_user_name,"tel_%s_%s",temp,randomCode);
	safe_free(randomCode);
	//safe_strdup(user->user_name,auto_user_name);
	safe_strdup(user->user_name,parv[1]);

	safe_strdup(user->tel,parv[1]);
	if ((!isNull(parv[3])) && check_nick(parv[3])) {
		safe_strdup(user->user_nick, parv[3]);
		safe_strdup(user->user_name, parv[3]);
	}
	safe_strdup(user->user_password, parv[4]);
	safe_free(temp);

	D_TimeStamp *timestamp=safe_alloc(sizeof(D_TimeStamp));
	D_getCurrectTime(timestamp);
	user->created_at = timestamp;
	ircd_log(LOG_ERROR,"client:%p",client);
	RegisterData *registerdata=safe_alloc(sizeof(RegisterData));
	registerdata->d_user=user;
	registerdata->openid=NULL;
	if(!isNull(parv[6])&&!isNull(parv[7])&&is_digist_string(parv[7],strlen(parv[7]))){
		safe_strdup(registerdata->openid,parv[6]);
		registerdata->thirdid=atoi(parv[7]);
		int len=0;
		D_third_login  *tempThirdLogin=queryImThirdLoginByOpenidAndThirdid(parv[6],registerdata->thirdid,&len);
		db_D_ThirdLoginFree(tempThirdLogin,len);
		if(len!=0){
			sendnumeric(client, RIGISTERSQLERROR, "third is already in used");
			return;
		}
	}

	//creat_gitlib_user(user->user_name,user->user_nick,user->user_password,user->email,client,registerdata);
	create_user(client,registerdata,NULL);
}

void create_user(Client *client,RegisterData *registerdata,char * email){
	D_User *userData=registerdata->d_user;
	char  *userName=safe_alloc(strlen(userData->user_name)+1);
	strcpy(userName,userData->user_name);
	int insert_status = 0;
	char insert_error_message[200]=""; 
	D_User * d_user = insertImUser(userData, &insert_status, insert_error_message);
	db_D_UserFree(userData,1);

	if (insert_status == -1) {
		ircd_log(LOG_ERROR, "regist is error and error %s", insert_error_message);
		sendnumeric(client, RIGISTERSQLERROR, insert_error_message);
		db_D_UserFree(d_user,1);
		return;
	}

	if(email){
		D_im_user_email * insertEmail = db_createUserEmail();
		safe_strdup(insertEmail->email,email);
		insertEmail->id = safe_alloc(sizeof(int));
		*(insertEmail->id) = *(d_user->id);
		insertEmail->permition = safe_alloc(sizeof(int));
		*(insertEmail->permition) = 0;
		int status =0;
		char errormessage[200];
		D_im_user_email * temp = insertImUserEmail(insertEmail,&status,errormessage);
		db_D_UserEmailFree(insertEmail,1);
		db_D_UserEmailFree(temp,status);
	}

	if(registerdata->openid){
		//查询openid是否存在，
		D_third_login *third_data=db_createThirdLogin();
		safe_strdup(third_data->nick_name,userName);
		safe_strdup(third_data->open_id,registerdata->openid);
		third_data->third_id=safe_alloc(sizeof(int));
		*(third_data->third_id)=registerdata->thirdid;
		third_data->user_id=safe_alloc(sizeof(int));
		*(third_data->user_id)=*(d_user->id);
		int third_statue=0;
		char insert_error_message1[200]=""; 
		
		D_third_login *tempThirdLogin=insertImThirdLogin(third_data,&third_statue,insert_error_message1);
		db_D_ThirdLoginFree(tempThirdLogin,third_statue);
		db_D_ThirdLoginFree(third_data,1);
		if(third_statue==-1){
			db_D_UserFree(d_user,1);
			ircd_log(LOG_ERROR, "insert third_login error:%s", insert_error_message);
			sendnumeric(client, RIGISTERSQLERROR, insert_error_message);
			return;
		}

	}
	sendnumeric(client, RIGISTERSUCCESS, (*d_user).user_nick);
	db_D_UserFree(d_user,1);
}

bool isNull(char *str) {
	return !strcmp(str, "null");
}
bool user_name_check(char *str) {
	int len = strlen(str);
	for (int i = 0; i < len; i++) {
		if (!isalnum(str[i])) {
			return false;
		}
	}
	return true;
}
bool check_tel(char *tel) {
	int tel_len = strlen(tel);
	for (int i = 0; i < tel_len; i++) {
		if (tel[i] < '0'||tel[i] > '9') {
			return false;
		}
	}
	return true;
}
bool check_sex(char *sex) {
	if ((!strcmp(sex, "1")) || (!strcmp(sex, "0"))) {
		return true;
	}
	return false;
}
bool check_email(char *email) {
	return true;
}
bool check_nick(char *nick) {
	return true;
}
//注册成功回调函数
void _registerSuccessCallfunc(HttpRequestData *requestData, long httpCode, Client *client,RegisterData *registerdata){
	D_User *userData=registerdata->d_user;
	ircd_log(LOG_ERROR,"_registerSuccessCallfunc,client:%p",client);
	cJSON *root;
	char *error_message, *userName,*email;
	int id;
	D_User * d_user;
	root = cJSON_Parse(requestData->response);
	if(root==NULL){
		ircd_log(LOG_ERROR, "regist is error and error %s", "gitlab register not success");
		sendnumeric(client, RIGISTERSQLERROR, "gitlab register not success");
		return;
	}
	ircd_log(LOG_ERROR,"_registerSuccessCallfunc,response:%s",cJSON_PrintUnformatted(root));
	switch (httpCode)
	{
	case 201://创建成功
		userName = cJSON_GetObjectItem(root, "username")->valuestring;
		email= cJSON_GetObjectItem(root, "email")->valuestring;
		id = cJSON_GetObjectItem(root, "id")->valueint;
		ircd_log(LOG_ERROR,"create user success ,userName:%s,email:%s,id:%d",userName, email, id);
		userData->git_id=&id;
		int insert_status = 0;
		char insert_error_message[200]=""; 
		d_user = insertImUser(userData, &insert_status, insert_error_message);
		db_D_UserFree(userData,1);
		if (insert_status == -1) {
			ircd_log(LOG_ERROR, "regist is error and error %s", insert_error_message);
			sendnumeric(client, RIGISTERSQLERROR, insert_error_message);
			break;
		}
		if(registerdata->openid){
			//查询openid是否存在，
			D_third_login *third_data=db_createThirdLogin();
			safe_strdup(third_data->nick_name,userName);
			safe_strdup(third_data->open_id,registerdata->openid);
			third_data->third_id=safe_alloc(sizeof(int));
			*(third_data->third_id)=registerdata->thirdid;
			third_data->user_id=safe_alloc(sizeof(int));
			*(third_data->user_id)=*(d_user->id);
			int third_statue=0;
			char insert_error_message1[200]=""; 
			D_third_login *tempThirdLogin=insertImThirdLogin(third_data,&third_statue,insert_error_message1);
			db_D_ThirdLoginFree(tempThirdLogin,third_statue);
			db_D_ThirdLoginFree(third_data,1);
			if(third_statue==-1){
				ircd_log(LOG_ERROR, "insert third_login error:%s", insert_error_message);
				sendnumeric(client, RIGISTERSQLERROR, insert_error_message);
				break;
			}

		}
		sendnumeric(client, RIGISTERSUCCESS, (*d_user).user_name);
		break;
	default://创建失败
		{

			cJSON *response_json = cJSON_GetObjectItem(root, "message");
			if(!response_json){
				safe_strdup(error_message,"unknown error message");
			}
			else if(response_json->valuestring){
				error_message=response_json->valuestring;
			}
			else{
				error_message=cJSON_PrintUnformatted(response_json);
			}
			ircd_log(LOG_ERROR, "regist is error and error %s", error_message);
			sendnumeric(client, RIGISTERSQLERROR, error_message);
			break;
		}
	}
	db_D_UserFree(d_user,1);
	cJSON_Delete(root);
}
void _registerFaileCallfunc(HttpRequestData *requestData, Client *client,RegisterData *userData){
	ircd_log(LOG_ERROR,"_registerFaileCallfunc,client:%p",client);
	ircd_log(LOG_ERROR, "regist is error and error %s", "gitlib server connect faile");
	if(!client){
		ircd_log(LOG_ERROR,"regist client is NULL");
	}
	sendnumeric(client, RIGISTERSQLERROR, "gitlib server connect faile");
}


/**
 * 邮箱注册账号
 * parv[1] 邮箱号
 * parv[2] 邮箱验证码
 * parv[3] 昵称
 * parv[4] 密码
 * parv[5] 第三方的openid
 * parv[6] 第三方的编号 0是QQ，1是微信
 */

CMD_FUNC(cmd_EmailRegister) {
	if (!IsAPPIdent(client)) {
		sendnumeric(client, ERR_WHITHOUTAPPIDENT);
		return;
	}
	if (parc != 7 || BadPtr(parv[6])) {
		sendnumeric(client, ERR_NEEDMOREPARAMS, "EREGISTER");
		return;
	}

	//增加验证注册信息的

	//

	if (isNull(parv[1])) {
		sendnumeric(client, REGISTERNEEDMOREPARAM, "email");
		return;
	}
	else {
		if (!check_email(parv[1])) {
			sendnumeric(client, RIGISTERPARAMNOTRIGHT, "email");
			return;
		}
		int UserEmailExitNum = 0;
		D_im_user_email *email_exit = queryImUserEmailByEmail(parv[1], &UserEmailExitNum);
		db_D_UserEmailFree(email_exit,UserEmailExitNum);
		if (UserEmailExitNum != 0) {
			sendnumeric(client, RIGISTERUSERNAMEISUSED);
			return;
		}

	}
	//验证验证邮箱码是否正确
	int sms_data_len = 0;
	D_im_sms *sms_data = queryImSMSByValueAndType(parv[1], SMS_STATUS_REGISTER, SMS_MODE_EMAIL, 5, &sms_data_len);
	if (sms_data_len != 1) {
		db_D_ImSMSFree(sms_data, sms_data_len);
		sendnumeric(client, SMSVALIDATIONFAILED);
		return;
	}
	if (strcmp(parv[2], sms_data->code)) {
		db_D_ImSMSFree(sms_data,sms_data_len);
		sendnumeric(client, SMSVALIDATIONFAILED);
		return;
	}

	*(sms_data->used) = 1;
	int sms_updata = 0;
	char s_sms_updata[255] = "";
	D_im_sms *sms_data_update = updataImSMS(sms_data, &sms_updata, s_sms_updata);
	db_D_ImSMSFree(sms_data,sms_data_len);
	db_D_ImSMSFree(sms_data_update,sms_updata);
	if (isNull(parv[3])) {
		sendnumeric(client, REGISTERNEEDMOREPARAM, "user_nick");
		return;
	}
	if (isNull(parv[4])) {
		sendnumeric(client, REGISTERNEEDMOREPARAM, "password");
		return;
	}

	D_User *user = db_createUser();
	char *temp = NULL;
	safe_strdup(temp, parv[1]);
	if (strlen(temp) > 15) {
		temp[15] = '\0';
	}
	// char *randomCode = random_digist(5);
	// char auto_user_name[31];
	// sprintf(auto_user_name, "tel_%s_%s", temp, randomCode);
	// safe_free(randomCode);
	// safe_strdup(user->user_name, auto_user_name);

	char  * email=NULL;
	safe_strdup(email,parv[1]);
	if ((!isNull(parv[3])) && check_nick(parv[3])) {
		safe_strdup(user->user_nick,parv[3]);
		safe_strdup(user->user_name,parv[3]);
	}
	safe_strdup(user->user_password,parv[4]);
	//char auto_user_tel[50];
	//sprintf(auto_user_tel, "tel_%s@ueim.com", temp);
	//safe_strdup(user->tel, auto_user_tel);
	safe_free(temp);

	D_TimeStamp *timestamp = safe_alloc(sizeof(D_TimeStamp));
	D_getCurrectTime(timestamp);
	user->created_at = timestamp;
	ircd_log(LOG_ERROR, "client:%p", client);
	
	RegisterData *registerdata = safe_alloc(sizeof(RegisterData));
	registerdata->d_user = user;
	registerdata->openid = NULL;
	if (!isNull(parv[5]) && !isNull(parv[6]) && is_digist_string(parv[6], strlen(parv[6]))) {
		safe_strdup(registerdata->openid, parv[5]);
		registerdata->thirdid = atoi(parv[6]);
		int len = 0;
		D_third_login  * tempThirdLogin = queryImThirdLoginByOpenidAndThirdid(parv[5], registerdata->thirdid, &len);
		db_D_ThirdLoginFree(tempThirdLogin,len);
		if (len != 0) {
			sendnumeric(client, RIGISTERSQLERROR, "third is already in used");
			return;
		}
	}

	//creat_gitlib_user(user->user_name,user->user_nick,user->user_password,user->email,client,registerdata);
	create_user(client, registerdata,email);
}





